import type { PiniaPluginContext } from 'pinia'

export interface PersistOptions {
  enabled?: boolean // 是否启用持久化
  strategies?: {
    key?: string // 存储的键名
    storage?: Storage // 存储方式，默认 localStorage
    paths?: string[] // 需要持久化的状态字段，不传则全部持久化
  }[]
}

// 默认配置
const defaultOptions: PersistOptions = {
  enabled: false,
  strategies: [
    {
      storage: localStorage,
    },
  ],
}

/**
 * Pinia 持久化插件
 * 使用方法：
 * export const useXxxStore = defineStore('xxx', () => {
 *   // ... store 定义
 * }, {
 *   persist: {
 *     enabled: true,
 *     strategies: [
 *       {
 *         key: 'custom_key', // 可选，自定义存储键名
 *         storage: localStorage, // 可选，默认 localStorage
 *         paths: ['field1', 'field2'], // 可选，指定持久化字段
 *       }
 *     ]
 *   }
 * })
 */
export function createPersistedState() {
  return (context: PiniaPluginContext) => {
    const { store, options } = context

    // 获取持久化配置
    const persistOptions = (options as any).persist as PersistOptions | undefined

    // 如果没有配置或未启用，直接返回
    if (!persistOptions || !persistOptions.enabled) {
      return
    }

    // 合并配置
    const strategies = persistOptions.strategies || defaultOptions.strategies || []

    // 遍历策略
    strategies.forEach((strategy) => {
      const storage = strategy.storage || localStorage
      const storeKey = strategy.key || `pinia_${store.$id}`
      const paths = strategy.paths

      // 从存储中恢复数据
      const savedState = storage.getItem(storeKey)
      if (savedState) {
        try {
          const data = JSON.parse(savedState)
          // 如果指定了字段，只恢复指定字段
          if (paths && Array.isArray(paths)) {
            paths.forEach((path) => {
              if (data[path] !== undefined) {
                store.$state[path] = data[path]
              }
            })
          } else {
            // 否则恢复所有字段
            store.$patch(data)
          }
        } catch (error) {
          console.error(`Failed to parse persisted state for ${storeKey}:`, error)
        }
      }

      // 监听状态变化，自动保存
      store.$subscribe(
        () => {
          const stateToSave = paths
            ? paths.reduce(
                (acc, path) => {
                  acc[path] = store.$state[path]
                  return acc
                },
                {} as Record<string, any>
              )
            : store.$state

          try {
            storage.setItem(storeKey, JSON.stringify(stateToSave))
          } catch (error) {
            console.error(`Failed to persist state for ${storeKey}:`, error)
          }
        },
        {
          detached: true, // 组件卸载后仍然保持订阅
        }
      )
    })
  }
}
